package puzzle.nurikabe.solver;

import puzzle.common.data.HatanException;
import puzzle.common.point.Direction;
import puzzle.common.solver.BoardRule;
import puzzle.nurikabe.data.NurikabeBoard;
import puzzle.nurikabe.data.ShimaState;
import puzzle.nurikabe.data.StateUtil;

class ShimaBorderRule implements BoardRule<NurikabeBoard> {

	public boolean apply(NurikabeBoard b) throws HatanException {
		boolean isChanged = false;
		for (int y = 0; y < b.height; y++) {
			for (int x = 0; x < b.width; x++) {
				int n = b.getBoardState(x, y);
				ShimaState s = null;
				if (StateUtil.isDeterminedShima(n)) {
					s = b.getShimaState(n);
				} else if (StateUtil.isUndeterminedShima(n)) {
					int k = StateUtil.decodeOwningShima(n);
					if (k != 0) {
						s = b.getShimaState(k);
					}
				}
				if (s != null && s.isDirty()) {
					for (Direction d : Direction.CLOCKWISE4) {
						int x1 = x + d.v.dx;
						int y1 = y + d.v.dy;
						int t = s.getPotential(x1, y1);
						if (t == 0) {
							isChanged |= b.setKabe(x1, y1);
						}
					}
				}
			}
		}
		
		for (ShimaState s : b.getShimaStates()) {
			if (!s.isFixed() && s.n == s.getArea()) {
				s.setFixed();
				isChanged |= setKabeOnAreaBorder(b, s);
			}
		}
		return isChanged;
	}

	private boolean setKabeOnAreaBorder(NurikabeBoard b, ShimaState s) throws HatanException {
		boolean isChanged = false;
		for (int y = 0; y < b.height; y++) {
			for (int x = 0; x < b.width; x++) {
				if (s.i == b.getBoardState(x, y)) {
					for (Direction d : Direction.CLOCKWISE4) {
						int x1 = x + d.v.dx;
						int y1 = y + d.v.dy;
						if (b.getBoardState(x1, y1) == 0) {
							isChanged |= b.setKabe(x + d.v.dx, y + d.v.dy);
						}
					}
				}
			}
		}
		return isChanged;
	}

//	public boolean apply(NurikabeBoard b) throws HatanException {
//		boolean isChanged = false;
//		for (ShimaState s : b.getShimaStates()) {
//			if (!s.isFixed() && s.n == s.getArea()) {
//				setKabeOnAreaBorder(b, s);
//				s.setFixed();
//			}
//		}
//		return isChanged;
//	}
//
//	private void setKabeOnAreaBorder(NurikabeBoard b, ShimaState s) throws HatanException {
//		for (int y = 0; y < b.height; y++) {
//			for (int x = 0; x < b.width; x++) {
//				if (s.i == b.getBoardState(x, y)) {
//					for (Direction d : Direction.CLOCKWISE4) {
//						int x1 = x + d.v.dx;
//						int y1 = y + d.v.dy;
//						if (b.getBoardState(x1, y1) == 0) {
//							b.setKabe(x + d.v.dx, y + d.v.dy);
//						}
//					}
//				}
//			}
//		}
//	}

}
